﻿/*-------------------------------------------------------------------------
* 命名空间: WaferSelectV3.ViewModels/RecipeSettingViewModel
* 类       名: RecipeSettingViewModel
* 功      能:  TD
* 时      间:  2024-04-29 17:57:33
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using Microsoft.Win32;
using OfficeOpenXml;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using WaferSelectV3.Common;
using WaferSelectV3.DAL.DataEntity;
using WaferSelectV3.DAL.LocalDataAccess;
using WaferSelectV3.Extensions;
using WaferSelectV3.Models;
using WaferSelectV3.Services;

namespace WaferSelectV3.ViewModels
{
    public class RecipeSettingViewModel : BindableBase, INavigationAware
    {

        private string? _importRecipeFile;
        /// <summary>
        /// 导入的配方名称
        /// </summary>
        public string? ImportRecipeFile
        {
            get { return _importRecipeFile; }
            set
            {
                _importRecipeFile = value;
                RaisePropertyChanged();
            }
        }



        public RecipeSettingViewModel()
        {
            ImportRecipeFile = PathDirProvider.RecipeImportFilename;
            SaveCommand = new DelegateCommand(DoSave);
            ImportCommand = new DelegateCommand(DoImport);
            ExportCommand = new DelegateCommand(DoExport);
        }


        /// <summary>
        /// 导出命令
        /// </summary>
        public DelegateCommand ExportCommand { get; private set; }
        private void DoExport()
        {
            try
            {
                string exportDir = PathDirProvider.RecipeImportDir;
                SaveFileDialog dialog = new SaveFileDialog();
                dialog.Title = "导出配方文件";
                dialog.Filter = "文档|*.csv;*.xls;*.xlsx";
                dialog.CheckFileExists = false;
                dialog.RestoreDirectory = true;
                dialog.FileName = ImportRecipeFile;
                bool? dialogResult = dialog.ShowDialog();
                if (dialogResult != null && dialogResult == false)
                {
                    return;
                }

                string filePath = dialog.FileName!;
                if (!string.IsNullOrEmpty(filePath))
                {
                    if (File.Exists(filePath))
                    {
                        var result = MessageBox.Show($"文件{Path.GetFileName(filePath)}已经存在,是否覆盖掉原来的文件", "文件操作提示框", MessageBoxButton.OKCancel, MessageBoxImage.Question);
                        if (result == MessageBoxResult.OK)
                        {
                            File.SetAttributes(filePath, FileAttributes.Normal);
                            File.Delete(filePath);
                        }
                        else
                        {
                            return;
                        }
                    }
                    // 先把导入的文件拷贝到导出路径文件中去(然后再写入就是修改),为什么要这样,以为我们目前就是默认只在原有的格式上修改,尽量不重新创建新的文件从头开始
                    File.Copy(Path.Combine(PathDirProvider.RecipeImportDir, ImportRecipeFile!), filePath);
                    DataResult saveResult = SaveRecipeModelToExcel(filePath);
                    if (saveResult.State)
                    {
                        MessageBox.Show("导出成功!", "操作成功", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                    else
                    {
                        MessageBox.Show($"导出失败,{saveResult.Message}", "操作失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                else
                {
                    MessageBox.Show($"导出配方失败:导出的文件名不能为空", "导出配方失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            catch (Exception ex)
            {
                LoggerHelper.WriteLogMain(ex.GetFullException(), LogType.Fatal);
                MessageBox.Show($"导出配方失败:{ex.Message}", "导出配方失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 导入命令,导入命令,只能将要导入的工单导入到界面
        /// </summary>
        public DelegateCommand ImportCommand { get; private set; }
        private void DoImport()
        {
            string importDir = PathDirProvider.RecipeImportDir;
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Title = "请选择导入的配方文件";
            dialog.Filter = "文档|*.csv;*.xls;*.xlsx";
            dialog.InitialDirectory = importDir;
            // 设置为true,下次打开的对话框和上次的是否保持一致
            dialog.RestoreDirectory = true;
            dialog.ShowDialog();
            string filePath = dialog.FileName; // 获取选中的文件的全路径名
            if (!string.IsNullOrEmpty(filePath))
            {
                var result = WorkingInfoAccess.GetWorkingInfo();
                if (result.State)
                {
                    var oldEntity = result.Data!;
                    oldEntity.RecipeImportDir = Path.GetDirectoryName(filePath);
                    oldEntity.RecipeImportFileName = Path.GetFileName(filePath);
                    var updateResult = WorkingInfoAccess.UpdateWorkingInfo(oldEntity);
                    if (!updateResult.State)
                    {
                        LoggerHelper.WriteLogMain(updateResult.Message!, LogType.Fatal);
                    }
                    else
                    {
                        PathDirProvider.RecipeImportDir = oldEntity.RecipeImportDir!;
                        PathDirProvider.RecipeImportFilename = oldEntity.RecipeImportFileName;
                        ImportRecipeFile = oldEntity.RecipeImportFileName;
                        // 要重新加载配方的值
                        ReloadRecipe();
                    }
                }
                else
                {
                    LoggerHelper.WriteLogMain(result.Message!, LogType.Fatal);
                }
            }
        }

        public DelegateCommand SaveCommand { get; private set; }
        private void DoSave()
        {
            // 保存工单的任务
            string savePath = Path.Combine(PathDirProvider.RecipeImportDir, ImportRecipeFile!);
            if (!File.Exists(savePath))
            {
                MessageBox.Show("保存的工单路径不存在,请先加载工单", "工单路径不存在", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            try
            {
                // 如果已经有Office进程和WPS进程将这个文件打开,先关闭再保存.
                if (FileOperateHelper.IsFileLocked(savePath))
                {
                    // 如果已经被占用
                    ProcessHelper.CloseOpenedExcelFileProcess(savePath);
                }

                File.SetAttributes(savePath, FileAttributes.Normal);
                DataResult result = SaveRecipeModelToExcel(savePath);
                if (!result.State)
                {
                    MessageBox.Show($"配方保存失败: {result.Message}", "保存失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                // 1. 保存成功以后,将这个配方要保存到生产配方中去
                File.SetAttributes(savePath, FileAttributes.Normal);
                string productionPath = Path.Combine(PathDirProvider.ProductionRecipeDir, ImportRecipeFile!);
                if (File.Exists(productionPath))
                {
                    File.SetAttributes(productionPath, FileAttributes.Normal);
                    File.Delete(productionPath);
                }
                // 参数1: 拷贝源,参数2: 拷贝目标文件 拷贝目标文件要不存在才行
                File.Copy(savePath, productionPath);
                MessageBox.Show("保存成功!", "操作成功", MessageBoxButton.OK, MessageBoxImage.Information);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetFullException(), "异常出错提示", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

        }

        //将UI上面的模型值,更新到其对应的Excel文件中去
        private DataResult SaveRecipeModelToExcel(string savePath)
        {
            DataResult result = new DataResult();
            File.SetAttributes(savePath, FileAttributes.Normal);
            try
            {
                ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
                ExcelPackage package = new ExcelPackage(savePath);
                // 读取工作簿中名为测试配方内容的工作表
                ExcelWorksheet sheet1 = package.Workbook.Worksheets["测试配方内容"];
                List<string> writeStr = new List<string>();
                List<string> noWriteList = new List<string>()
                {
                    "线激光测量","电阻率测量","尺寸","前崩边","后崩边","左崩边","右崩边","上脏污","下脏污","隐裂1","隐裂2"
                };
                for (int i = 0; i < DetectedRuleList!.Count; i++)
                {
                    var model = DetectedRuleList![i];
                    writeStr.Clear();
                    writeStr.Add(string.IsNullOrEmpty(model.DetectedName) ? "" : model.DetectedName);
                    writeStr.Add(string.IsNullOrEmpty(model.Description) ? "" : model.Description);
                    writeStr.Add(string.IsNullOrEmpty(model.Unit) ? "" : model.Unit);
                    writeStr.Add(string.IsNullOrEmpty(model.Precis) ? "" : model.Precis);
                    writeStr.Add(string.IsNullOrEmpty(model.Level01Val) ? "" : model.Level01Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level02Val) ? "" : model.Level02Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level03Val) ? "" : model.Level03Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level04Val) ? "" : model.Level04Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level05Val) ? "" : model.Level05Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level06Val) ? "" : model.Level06Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level07Val) ? "" : model.Level07Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level08Val) ? "" : model.Level08Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level09Val) ? "" : model.Level09Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level10Val) ? "" : model.Level10Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level11Val) ? "" : model.Level11Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level12Val) ? "" : model.Level12Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level13Val) ? "" : model.Level13Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level14Val) ? "" : model.Level14Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level15Val) ? "" : model.Level15Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level16Val) ? "" : model.Level16Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level17Val) ? "" : model.Level17Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level18Val) ? "" : model.Level18Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level19Val) ? "" : model.Level19Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level20Val) ? "" : model.Level20Val);
                    writeStr.Add(string.IsNullOrEmpty(model.Level21Val) ? "" : model.Level21Val);

                    if (!noWriteList.Contains(writeStr[0]))
                    {
                        // 如果不包含这些标题,就写入.写入的时候,注意是错一位的.
                        for (int j = 1; j <= writeStr.Count; j++)
                        {
                            sheet1.Cells[i + 2, j].Value = writeStr[j - 1];
                        }
                    }
                }

                // 保存Sheet2的值.
                ExcelWorksheet sheet2 = package.Workbook.Worksheets["测试配方配置"];//读取工作簿中名为"Sheet2"的工作表
                for (int i = 0; i < RecipeConfigList!.Count; i++)
                {
                    var model = RecipeConfigList![i];
                    writeStr.Clear();
                    writeStr.Add(model.Level.ToString());
                    writeStr.Add(model.IsUsed ? "TRUE" : "FALSE");
                    writeStr.Add(string.IsNullOrEmpty(model.LevelType) ? "" : model.LevelType);
                    writeStr.Add(string.IsNullOrEmpty(model.TypeDescription) ? "" : model.TypeDescription);
                    writeStr.Add(string.IsNullOrEmpty(model.BoxesInto) ? "" : model.BoxesInto);
                    for (int j = 1; j <= writeStr.Count; j++)
                    {
                        sheet2.Cells[i + 2, j].Value = writeStr[j - 1];
                    }
                }
                package.Save();
                package.Dispose();
                result.State = true;

            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        private ObservableCollection<RecipeLevelBoxModel>? _recipeConfigList;

        public ObservableCollection<RecipeLevelBoxModel>? RecipeConfigList
        {
            get { return _recipeConfigList; }
            set { SetProperty(ref _recipeConfigList, value); }
        }


        /// <summary>
        /// 配方规则数据源
        /// </summary>
        private ObservableCollection<RecipeDectectedRuleModel>? _detectedRuleList;
        public ObservableCollection<RecipeDectectedRuleModel>? DetectedRuleList
        {
            get { return _detectedRuleList; }
            set { SetProperty(ref _detectedRuleList, value); }
        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            DetectedRuleList = null;
            RecipeConfigList = null;
        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            ReloadRecipe();
        }

        private void ReloadRecipe()
        {
            try
            {
                // 1. 先获取当前的导入目录和导入文件
                string importRecipePath = Path.Combine(PathDirProvider.RecipeImportDir, ImportRecipeFile!);
                if (!File.Exists(importRecipePath))
                {
                    MessageBox.Show($"配方文件不存在,请重新导入配方文件", "配方导入失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                // 加载文件,然后显示内容
                DataResult<List<List<string>>> ruleContentResult = DetectedRuleHelper.GetRecipeDetectedRuleContent(importRecipePath);
                if (!ruleContentResult.State)
                {
                    LoggerHelper.WriteLogMain(ruleContentResult.Message!, LogType.Fatal);
                    MessageBox.Show($"配方加载失败: {ruleContentResult.Message}", "配方加载失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                var ruleContentData = ruleContentResult.Data;
                DetectedRuleList = new ObservableCollection<RecipeDectectedRuleModel>();
                foreach (var ruleContent in ruleContentResult.Data!)
                {
                    int dataLen = ruleContent.Count;
                    var modelObj = new RecipeDectectedRuleModel()
                    {
                        DetectedName = 0 < dataLen ? ruleContent[0].Trim('\"') : string.Empty,
                        Description = 1 < dataLen ? ruleContent[1].Trim('\"') : string.Empty,
                        Unit = 2 < dataLen ? ruleContent[2].Trim('\"') : string.Empty,
                        Precis = 3 < dataLen ? ruleContent[3].Trim('\"') : string.Empty,
                        Level01Val = 4 < dataLen ? ruleContent[4].Trim('\"') : string.Empty,
                        Level02Val = 5 < dataLen ? ruleContent[5].Trim('\"') : string.Empty,
                        Level03Val = 6 < dataLen ? ruleContent[6].Trim('\"') : string.Empty,
                        Level04Val = 7 < dataLen ? ruleContent[7].Trim('\"') : string.Empty,
                        Level05Val = 8 < dataLen ? ruleContent[8].Trim('\"') : string.Empty,
                        Level06Val = 9 < dataLen ? ruleContent[9].Trim('\"') : string.Empty,
                        Level07Val = 10 < dataLen ? ruleContent[10].Trim('\"') : string.Empty,
                        Level08Val = 11 < dataLen ? ruleContent[11].Trim('\"') : string.Empty,
                        Level09Val = 12 < dataLen ? ruleContent[12].Trim('\"') : string.Empty,
                        Level10Val = 13 < dataLen ? ruleContent[13].Trim('\"') : string.Empty,
                        Level11Val = 14 < dataLen ? ruleContent[14].Trim('\"') : string.Empty,
                        Level12Val = 15 < dataLen ? ruleContent[15].Trim('\"') : string.Empty,
                        Level13Val = 16 < dataLen ? ruleContent[16].Trim('\"') : string.Empty,
                        Level14Val = 17 < dataLen ? ruleContent[17].Trim('\"') : string.Empty,
                        Level15Val = 18 < dataLen ? ruleContent[18].Trim('\"') : string.Empty,
                        Level16Val = 19 < dataLen ? ruleContent[19].Trim('\"') : string.Empty,
                        Level17Val = 20 < dataLen ? ruleContent[20].Trim('\"') : string.Empty,
                        Level18Val = 21 < dataLen ? ruleContent[21].Trim('\"') : string.Empty,
                        Level19Val = 22 < dataLen ? ruleContent[22].Trim('\"') : string.Empty,
                        Level20Val = 23 < dataLen ? ruleContent[23].Trim('\"') : string.Empty,
                        Level21Val = 24 < dataLen ? ruleContent[24].Trim('\"') : string.Empty,
                    };
                    DetectedRuleList.Add(modelObj);
                }

                DataResult<List<RecipeLevelBoxModel>> recipeDetectedLevelResult = ExcelHelper.GetRecipeLevelBoxInfo(importRecipePath);
                if (!recipeDetectedLevelResult.State)
                {
                    LoggerHelper.WriteLogMain(recipeDetectedLevelResult.Message!, LogType.Fatal);
                    MessageBox.Show($"配方加载失败: {recipeDetectedLevelResult.Message}", "配方加载失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                RecipeConfigList = new ObservableCollection<RecipeLevelBoxModel>(recipeDetectedLevelResult.Data!);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetFullException(), "工单信息加载出错", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }
}
